<?php 
// Данный скрипт хранится в UTF-8 т.к. используются русские символы в выводе

interface IFactoryFilter {
   /**
    * Получить HTML представление фильтра
    * @return html код фильтра
    */
   public function getHTMLView();
   /**
    * Добавить данные в модель запроса
    * @param $sql - ссылка на модель запроса (пареметры подстановки аргументов %s, %d)
    * @param $args - ссылка на массив аргументов 
    * @return unknown_type
    */
   public function rewriteSQL(&$sql, &$args);
   public function __toString();
};

class FactoryHelper{
   /**
    * Проверка корректности переданной для перезаписи модели SQL-запроса
    * @param $sql
    * @param $args
    * @return unknown_type
    */
   public function CheckArgs(&$sql, &$args){
      if(!is_array($sql)) 
         throw new Exception("SQL-query not an array (AlphabetFilter error)", ERROR_CRITICAL);
      if(!is_array($args)) 
         throw new Exception("Arguments not an array (AlphabetFilter error)", ERROR_CRITICAL);
      if(count($sql) == 0) 
         throw new Exception("SQL-query is empty (AlphabetFilter error)", ERROR_CRITICAL);
   }
}

// --

class AlphabetFilter extends FactoryHelper implements IFactoryFilter{
   private $m_FName = "alp";
   // --
   private $Alphabet = array(
	0	=> array('А','Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З', 'И', 'К', 'Л', 'М',
					  'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Х', 'Х', 'Ц', 'Ч', 'Ш',
					  'Щ', 'Э', 'Ю', 'Я'),
	1	=> array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
					 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z')
   );
   
   // --
   public function __construct($FiltNum_ = 0){
      if($FiltNum_ != 0) 
         $this->m_FName = $this->m_FName.(int)$FiltNum_;
   }
   /**
    * Вернуть массив символов запрошенного алфавита
    * @param $alp
    * @return unknown_type
    */
   public function GetAlphabet($alp){
      if($this->CheckAlphabet($alp))
         return $this->Alphabet[$alp];
      else
      return null;
   }
   /**
    * Получить расширенное имя алфавита
    * @param $alp
    * @return unknown_type
    */
   public function GetAlphabetAlias($alp){
      switch($alp){
         case 0:
            return t('Russian');
         case 1:
            return t('English');
      }
      throw new Exception("Unknown alphabet", ERROR_CRITICAL);
   }
   /**
    * Проверка на наличие запрошенного алфавита
    * @param $alp
    * @return unknown_type
    */
   public function CheckAlphabet($alp){
      return array_key_exists($alp, $this->Alphabet);
   }

   /**
    * Проверить принадлежность кода символа заданному алфавиту 
    * @param $char - код символа
    * @param $alp - код алфавита
    * @return true - если символ пренадлежит алфавиту
    */
   public function CheckChar($char, $alp){
      return ($this->CheckAlphabet($alp)) ? array_key_exists($char, $this->Alphabet[$alp]):false;
   }
   
   /**
    * Обрамить алфавит тегами ссылок 
    * @see AlphabetFilter::getHTMLView
    */
   private function CharWrapper(&$item, $key, $langID){
      // Подменяем только параметры данного фильтра в строке запроса 
      $myGET = $_GET;
      $myGET[$this->m_FName] = $langID.".".$key;
   
   //@todo возможна неправильная работа при "чистых URL"
      $item = l($item, $_SERVER['q'], array('query'=> $myGET));
   }
   
   /**
	 * @see IFactoryFilter
    */
   public function rewriteSQL(&$sql, &$args){
      $this->CheckArgs($sql, $args);
      if(!$this->isEnabled()) return;
      $matches = array();
      if(!preg_match("/([0-9]+).([0-9]+)/", $_GET[$this->m_FName], $matches))
         throw new Exception("Wrong GET param (".$this.")", ERROR_HACKING);
      $alp = (int)$matches[1];
      $letter = (int)$matches[2];
      if(!$this->CheckChar($letter, $alp)) 
         throw new Exception("Alphabet or letter doesn't exist", ERROR_WARNING);
      
      $and = "";
      if(count($sql['where']) > 0)
        $and = "and"; 
      if($alp == 0)
         $sql['where'][] = $and." runame like '%s%%'";
      if($alp == 1)
         $sql['where'][] = $and." engname like '%s%%'";
         
      $args[] = $this->Alphabet[$alp][$letter];
      return;
   }
   /**
    * @see IFactoryFilter
    */
   //@todo Нужно сделать через базовые элементы Друпала
   public function getHTMLView(){
   //@todo сделать отдельным элементом друпала + сделать его кэширование

	// HEADER
	$out = '<br><div class="sort-panel">';
	$out.= '<div class="sort-panel-header">'.t('Alphabet panel').'</div>';
	$out.= '<div class="sort-panel-body" style="display: none">';
   	foreach($this->Alphabet as $lang => $alph){
      	$out.= '<div class="alphabet-sign">'.$this->GetAlphabetAlias($lang).'</div>';
      	$out.= '<div class="alphabet-letters">';
      	array_walk($alph, array($this, 'CharWrapper'), $lang);
      	$out.= implode(', ', $alph);
      	$out.= '</div>';
   	}
   	if($this->isEnabled()){
   	   // Убираем параметры фильтра из строки запроса
   	   $myGET = $_GET;
   	   $myGET[$this->m_FName] = NULL;
   	   unset($myGET[$this->m_FName]);
         $out.='<div class="filter-clear">'.l('Clear', $_SERVER['q'], array('query' => $myGET)).'</div>';
   	}
   	$out.= '</div></div>';
   	return $out;
   }
   public function isEnabled(){
   	return (isset($_GET[$this->m_FName]))? TRUE : FALSE;
   }
   
   public function __toString(){
      return __CLASS__;
   }
};

// --

/**
 * 
 * @author Darklight
 */
class VisibleFilter extends FactoryHelper implements IFactoryFilter{
   private $m_FName = "vis";
   private $m_Mode;
   
   /**
    * @param $Mode_ - тип обработки скрытых объектов: <br> 
    * "hidden" - только скрытые, <br> 
    * "all" - все, <br> 
    * "unhidden" - только открытые
    * @return unknown_type
    */
   public function __construct($Mode_ = "unhidden", $FiltNum_ = 0){
      switch($Mode_){
         case "unhidden": $this->m_Mode = 0; break;
         case "hidden":   $this->m_Mode = 1; break;
         case "all":  
            if(!isset($_GET[$this->m_FName])){ 
               $this->m_Mode = 2; 
               return;
            }
            $matches = array();
            if(!preg_match("/(0|1|2)/", $_GET[$this->m_FName], $matches))
               throw new Exception("Error: wrong GET param in ".$this, ERROR_HACKING);
            $this->m_Mode = (int)$matches[1];
         break;
         default:         $this->m_Mode = 2; break;
      }
      if($FiltNum_ != 0) 
         $this->m_FName = $this->m_FName.(int)$FiltNum_;
   }
   public function rewriteSQL(&$sql, &$args){
      $this->CheckArgs($sql,$args);
      
      $and = "";
      if(count($sql['where']) > 0)
        $and = "and";
        
       switch($this->m_Mode){
          case 0:
             $sql['where'][]=$and." visible = %s";
             $args[] = 1;
          break;
          case 1:
             $sql['where'][]=$and." visible = %s";
             $args[] = 0;
          break;
          case 2:  return; break;
          default: return; break;
       } 
   }
   public function getHTMLView(){ 
      //@todo сделать отдельным элементом друпала + сделать его кэширование

      $myGET = $_GET;
   	$out = '<br><div class="sort-panel">';
   	$out.= '<div class="sort-panel-header">'.t('Visible panel').'</div>';
   	$out.= '<div class="sort-panel-body" style="display: none">';
   	$myGET[$this->m_FName] = 0;
   	$out.= l(t('Show unhidden'),$_SERVER['q'], array('query' =>$myGET)).' ';
   	$myGET[$this->m_FName] = 1;
   	$out.= l(t('Show hidden'),$_SERVER['q'], array('query' =>$myGET)).' ';
   	$myGET[$this->m_FName] = 2;
   	$out.= l(t('Show all'),$_SERVER['q'], array('query' =>$myGET));
      if(isset($_GET[$this->m_FName])){
       // Убираем параметры фильтра из строки запроса
          $myGET = $_GET;
      	 $myGET[$this->m_FName] = NULL;
      	 unset($myGET[$this->m_FName]);
            $out.='<div class="filter-clear">'.l('Clear', $_SERVER['q'], array('query' => $myGET)).'</div>';
      	}
      $out.= '</div></div>';
      return $out;
   }
   public function isEnabled(){
   	return (isset($_GET[$this->m_FName]))? TRUE : FALSE;
   }
   public function __toString(){
      return __CLASS__;
   }
}

/**
 * Фильтр выборки записей с определённой серией
 * @author Darklight
 */
class WhereSeriesFilter extends FactoryHelper implements IFactoryFilter{
   private $m_sid = 0;
   public function __construct($SID_ = 0){
      $this->m_sid = (int)$SID_;  
   }
   public function rewriteSQL(&$sql, &$args){
      if($this->m_sid == 0)
         throw new Exception("Error: Series id = 0 in ".$this, ERROR_WARNING);
      $this->CheckArgs($sql,$args);
      
      $and = "";
      if(count($sql['where']) > 0)
        $and = "and";
      $sql['where'][]=$and." sid = %s";
      $args[] = $this->m_sid; 
   }
   public function getHTMLView(){ 
      return '';
   }

   public function __toString(){
      return __CLASS__;
   }
}

/**
 * Фильтр выборки записей с определённой серией
 * @author Darklight
 */
class WherePTypeFilter extends FactoryHelper implements IFactoryFilter{
   private $m_ptid = 0;
   public function __construct($PTID_ = 0){
      $this->m_ptid = (int)$PTID_;  
   }
   public function rewriteSQL(&$sql, &$args){
      if($this->m_ptid == 0)
         throw new Exception("Error: Production type id = 0 in ".$this, ERROR_WARNING);
      $this->CheckArgs($sql,$args);
      
      $and = "";
      if(count($sql['where']) > 0)
        $and = "and";
      $sql['where'][]=$and." ptid = %s";
      $args[] = $this->m_ptid; 
   }
   public function getHTMLView(){ 
      return '';
   }
   
   public function __toString(){
      return __CLASS__;
   }
}
?>